using System.Collections.Generic;
using System.Linq;

using Vibstudio.X4NET.Text;

namespace Vibstudio.X4NET.Csv
{
    public class CsvReader
    {
        #region Constants

        private const char FIELD_SEPARATOR = ';';
        private const char NEW_LINE_SEPARATOR = '\n';

        #endregion

        public static string GetHeader(string csv)
        {
            return string.IsNullOrEmpty(csv)
                       ? string.Empty
                       : csv.Split(NEW_LINE_SEPARATOR)[0].StripEscape();
        }

        public static string[] GetHeaderFields(string csv)
        {
            string header = GetHeader(csv);

            return string.IsNullOrEmpty(header)
                       ? new string[] { }
                       : header.Split(FIELD_SEPARATOR);
        }

        public static string[] GetRowFields(string csvRow)
        {
            return string.IsNullOrEmpty(csvRow)
                       ? new string[] {}
                       : csvRow.StripEscape().Split(FIELD_SEPARATOR);
        }

        public static string[] GetRows(string csv, CsvTargetRowsType targetRowsType, bool includeEmptyRows)
        {
            var rowList = new List<string>();

            if (!string.IsNullOrEmpty(csv))
            {
                switch (targetRowsType)
                {
                    case CsvTargetRowsType.Header:
                        rowList.Add(GetHeader(csv));
                        break;
                    case CsvTargetRowsType.Body:
                        rowList.AddRange(GetBody(csv));
                        break;
                    default:
                        rowList.AddRange(GetAllRows(csv));
                        break;
                }
            }

            TreatEmpyRows(ref rowList, includeEmptyRows);

            return rowList.ToArray();
        }

        public static int GetLenght(string csv)
        {
            return GetRows(csv, CsvTargetRowsType.All, true).Length;
        }

        public static int GetLenght(string csv, bool includeEmptyRows)
        {
            return GetRows(csv, CsvTargetRowsType.All, includeEmptyRows).Length;
        }

        #region Private methods

        private static IEnumerable<string> GetBody(string csv)
        {
            var rowList = new List<string>();

            if (!string.IsNullOrEmpty(csv))
            {
                string[] rows = csv.Split(NEW_LINE_SEPARATOR);
                rowList.AddRange(rows.Where((t, i) => i > 0).Select(StringExtensions.StripEscape));
            }

            return rowList;
        }

        private static IEnumerable<string> GetAllRows(string csv)
        {
            var rowList = new List<string>();

            if (!string.IsNullOrEmpty(csv))
            {
                string[] rows = csv.Split(NEW_LINE_SEPARATOR);
                rowList.AddRange(rows.Select(StringExtensions.StripEscape));
            }

            return rowList;
        }

        private static void TreatEmpyRows(ref List<string> list, bool include)
        {
            if (!include)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i] == string.Empty)
                        list.RemoveAt(i);
                }
            }
        }
        
        #endregion
    }
}